%%%-------------------------------------------------------------------
%%% File    : cache_ets.erl
%%% Author  :  <vjache>
%%% Description : 
%%%
%%% Created : 29 Apr 2009 by  <vjache>
%%%-------------------------------------------------------------------
-module(cache_ets).

%% API
-export([
		 update_counter/3,
		 put/3,
		 put_new/3,
		 get/3,
		 obtain/3,
		 foldl/3,
		 foldr/3,
		 to_list/1,
		 cleanup/1,
		 delete/2,
		 size/1
		 ]).

%%====================================================================
%% API
%%====================================================================
%%--------------------------------------------------------------------
%% Function: 
%% Description:
%%--------------------------------------------------------------------

update_counter(CacheId,Key,Incr) when is_integer(Incr) ->
	Tid=cache(CacheId),
	ets:update_counter(Tid, Key, Incr).
put(CacheId,Key,Value) ->
	Tid=cache(CacheId),
	true=ets:insert(Tid, {Key,Value}),
	ok.
put_new(CacheId,Key,Value) ->
	Tid=cache(CacheId),
	ets:insert_new(Tid, {Key,Value}).
get(CacheId,Key,NullFun) when is_function(NullFun,0) ->
	Tid=cache(CacheId),
	case ets:lookup(Tid, Key) of
		[] ->
			NullFun();
		[{Key,Value}] ->
			Value
	end;
get(CacheId,Key,Null) ->
	Tid=cache(CacheId),
	case ets:lookup(Tid, Key) of
		[] ->
			Null;
		[{Key,Value}] ->
			Value
	end.
obtain(CacheId,Key,{Module,Fun,Args}) ->
	obtain(CacheId,Key,
		   fun()->
				   apply(Module,Fun,Args)
		   end);
obtain(CacheId,Key,Fun) when is_function(Fun) ->
	Tid=cache(CacheId),
	case ets:lookup(Tid, Key) of
		[] ->
			Value=Fun(),
			true=ets:insert_new(Tid, {Key,Value}),
			Value;
		[{Key,Value}] ->
			Value
	end.
size(CacheId) ->
	Tid=cache(CacheId),
	ets:info(Tid, size).
cleanup(CacheId) ->
	case get(CacheKey={'$ets.cache',CacheId}) of
		undefined ->
			ok;
		Tid ->
			(catch ets:delete(Tid)),
			erase(CacheKey),
			ok
	end.
delete(CacheId,Key) ->
	true=ets:delete(cache(CacheId), Key),
	ok.
foldl(CacheId,FoldFun,Acc0) ->
	ets:foldl(FoldFun, Acc0, cache(CacheId)).
foldr(CacheId,FoldFun,Acc0) ->
	ets:foldr(FoldFun, Acc0, cache(CacheId)).

to_list(CacheId) ->
	foldl(CacheId,
		  fun(KvPair,AccIn)->
				  [KvPair|AccIn]
		  end,[]).
%%====================================================================
%% Internal functions
%%====================================================================
cache(CacheId) ->
	case get(CacheKey={'$ets.cache',CacheId}) of
		undefined ->
			undefined=put(CacheKey,T=ets:new('$ets.cache', [set,private])),
			T;
		Tid ->
			Tid
	end.

